package com.xdxc.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.xdxc.mapper.TempUserAnswerMapper;
import com.xdxc.model.entity.TempUserAnswer;
import com.xdxc.service.serviceinterface.TempUserAnswerService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

import static cn.hutool.core.thread.ThreadUtil.sleep;

@Service
@Slf4j
public class TempUserAnswerServiceImpl extends ServiceImpl<TempUserAnswerMapper, TempUserAnswer> implements TempUserAnswerService {

    @Autowired
    private  TempUserAnswerMapper mapper;

    private static final int MAX_RETRY_TIMES = 3;
    private static final long RETRY_INTERVAL_MS = 100;

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public void safeBatchUpsert(List<TempUserAnswer> entities) {

        // 1. 按主键去重
        Map<Long, TempUserAnswer> uniqueEntities = entities.stream()
                .collect(Collectors.toMap(
                        TempUserAnswer::getId,
                        Function.identity(),
                        (oldVal, newVal) -> oldVal.getVersion() > newVal.getVersion() ? oldVal : newVal
                ));

        // 2. 分批处理（每批50条）
        Lists.partition(new ArrayList<>(uniqueEntities.values()), 50).forEach(batch -> {
            try {
                // 3. 执行批量操作
                int affected = mapper.batchUpsert(batch);
                log.info("批量操作影响行数: {}", affected);
                // 4. 立即提交当前事务
                TransactionAspectSupport.currentTransactionStatus().flush();
            } catch (Exception e) {
                // 5. 单条重试
                batch.forEach(this::retrySingleRecord);
                throw e;
            }
        });
    }
    private void retrySingleRecord(TempUserAnswer entity) {
        for (int i = 0; i < 3; i++) {
            try {
                // 先尝试更新
                int updated = mapper.updateById(entity);
                if (updated == 0) {
                    // 不存在则插入
                    mapper.insert(entity);
                }
                log.info("单条记录恢复成功[id={}]", entity.getId());
                return;
            } catch (Exception e) {
                log.warn("单条重试失败[id={}, 重试次数={}]", entity.getId(), i+1, e);
                sleep(100 * (i + 1));
            }
        }
        log.error("单条记录最终恢复失败[id={}]", entity.getId());
    }
    private void executeWithRetry(Runnable operation) {
        int retryCount = 0;
        while (retryCount <= MAX_RETRY_TIMES) {
            try {
                operation.run();
                return;
            } catch (DataAccessException e) {
                if (isDeadlock(e) && retryCount < MAX_RETRY_TIMES) {
                    retryCount++;
                    try {
                        Thread.sleep(RETRY_INTERVAL_MS * (long) Math.pow(2, retryCount));
                        log.warn("检测到死锁，第{}次重试...", retryCount);
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                        throw new RuntimeException("重试被中断", ie);
                    }
                } else {
                    throw e;
                }
            }
        }
    }
    private boolean isDeadlock(DataAccessException e) {
        return e.getCause() != null
                && e.getCause().getMessage().contains("Deadlock");
    }


}
